import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class AppScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

class AssetImages {
  static const String ia_100000028 =
      'assets/images/on_boarding/ia_100000028.png';
  static const String iconWatch_1 =
      'assets/images/on_boarding/icon_watch_1.png';
  static const String iconWatch_2 =
      'assets/images/on_boarding/icon_watch_2.png';
  static const String iconWatch_3 =
      'assets/images/on_boarding/icon_watch_3.png';
  static const String iconWatch_4 =
      'assets/images/on_boarding/icon_watch_4.png';
}

class WatchPage extends StatefulWidget {
  const WatchPage({Key? key}) : super(key: key);

  @override
  State<WatchPage> createState() => _WatchPageState();
}

class _WatchPageState extends State<WatchPage> {
  /// 监听动画进度
  final ValueNotifier<double> _animationProgress = ValueNotifier(0.0);

  /// 指向底部按钮的 globalKey
  final _button = GlobalKey();

  /// 滑动页面控制器
  final _pageController = PageController();

  /// 数据源
  final _watchPageList = WatchPageModel.list();

  @override
  void initState() {
    /// 将动画进度和页面滑动绑定在一起
    _pageController.addListener(() {
      _animationProgress.value = _pageController.page!;
    });
    super.initState();
  }

  @override
  void dispose() {
    /// 在 dispose 的时候释放
    _pageController.dispose();
    _animationProgress.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnnotatedRegion(
      value: SystemUiOverlayStyle.light,
      child: Scaffold(
        appBar: AppBar(
          title: Text('WatchPage'),
        ),
        body: Stack(
          children: [
            AnimatedBuilder(
              animation: _animationProgress,
              builder: (_, __) => CustomPaint(
                painter: FlowPainter(
                  context: context,
                  animationProgress: _animationProgress,
                  target: _button,
                  colors: List.generate(_watchPageList.length,
                      (index) => _watchPageList[index].color),
                ),
              ),
            ),

            /// PageView
            PageView.builder(
              controller: _pageController,
              scrollBehavior: AppScrollBehavior(),
              itemCount: _watchPageList.length,
              itemBuilder: (BuildContext context, int index) {
                return _tempPage(index);
              },
            ),
            Align(
              /// 添加底部按钮

              alignment: Alignment.bottomCenter,
              child: Padding(
                padding: const EdgeInsets.only(bottom: 60),
                child: ClipOval(
                  child: AnimatedBuilder(
                    /// 给底部按钮添加动画
                    animation: _animationProgress,
                    builder: (_, __) {
                      /// 当前动画进度（用页面之间的拖动来计算）
                      final progress = _animationProgress.value -
                          _animationProgress.value.floor();

                      /// 按钮的透明度
                      double opacity = 0;

                      /// 按钮的位置
                      double iconPosition = 0;

                      /// 按钮背景颜色
                      int colorIndex;

                      if (progress < 0.5) {
                        /// 可根据个人喜好调整透明度、位置
                        opacity = (progress - 0.5) * -2;
                        iconPosition = 80 * -progress;
                        colorIndex = _animationProgress.value.floor() + 1;
                      } else {
                        colorIndex = _animationProgress.value.floor() + 2;
                        iconPosition = -80;
                      }

                      if (progress > 0.9) {
                        iconPosition = -250 * (1 - progress) * 10;
                        opacity = (progress - 0.9) * 10;
                      }

                      colorIndex = colorIndex % _watchPageList.length;

                      return SizedBox(
                        key: _button,
                        width: 64,
                        height: 64,
                        child: Transform.translate(
                          offset: Offset(iconPosition, 0),
                          child: Container(
                            decoration: BoxDecoration(
                              shape: BoxShape.circle,
                              color: _watchPageList[colorIndex].color,
                            ),
                            child: Icon(
                              Icons.chevron_right,
                              color: Colors.white.withOpacity(opacity),
                              size: 30,
                            ),
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }

  /// 先写一个简单的 page
  Widget _tempPage(int index) {
    return Align(
      alignment: Alignment.topCenter,
      child: Container(
        width: double.infinity,
        height: double.infinity,
        // color: _watchPageList[index].color,
        child: Padding(
          padding: const EdgeInsets.only(top: 200),
          child: Text(
            'PAGE $index',
            textAlign: TextAlign.center,
            style: TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 50,
              color: Colors.white,
            ),
          ),
        ),
      ),
    );
  }
}

/// 手表页面模型
class WatchPageModel {
  /// 手表图片
  String image;

  /// 描述视图
  Widget description;

  /// 背景颜色
  Color color;

  WatchPageModel({
    required this.image,
    required this.color,
    required this.description,
  });

  /// 预先准备好的 Apple Watch 数据源（模型数组）
  static List<WatchPageModel> list() {
    return [
      WatchPageModel(
        image: AssetImages.ia_100000028,
        color: Colors.black,
        description: Text.rich(
          TextSpan(
            style: TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.bold,
              fontSize: 17,
            ),
            children: [
              TextSpan(text: '健康的未来，\n现在戴上。\n\n'),
              TextSpan(
                  text: 'RMB 3199 起',
                  style: TextStyle(
                    fontSize: 17,
                  )),
            ],
          ),
          textAlign: TextAlign.center,
        ),
      ),
      WatchPageModel(
        image: 'assets/images/icon_watch_1.png',
        color: Color(0xff5c6bc0),
        description: WatchPageModel.descriptionWidget(
            model: '编织单圈表带\n\n',
            price: 3199,
            intro:
                '铝金属表壳十分轻盈，采用 100% 再生的航空级铝金属制成。\n\n编织单圈表带采用再生纱与硅胶丝交错编织而成，无表扣式弹性设计令佩戴格外舒适。'),
      ),
      WatchPageModel(
        image: 'assets/images/icon_watch_2.png',
        color: Color(0xffff9100),
        description: WatchPageModel.descriptionWidget(
            model: '回环式运动表带\n\n',
            price: 3199,
            intro:
                '铝金属表壳十分轻盈，采用 100% 再生的航空级铝金属制成。\n\n编织单圈表带采用再生纱与硅胶丝交错编织而成，无表扣式弹性设计令佩戴格外舒适。'),
      ),
      WatchPageModel(
        image: 'assets/images/icon_watch_3.png',
        color: Color(0xffE8B896),
        description: WatchPageModel.descriptionWidget(
            model: '运动型表带\n\n',
            price: 3199,
            intro:
                '铝金属表壳十分轻盈，采用 100% 再生的航空级铝金属制成。\n\n运动型表带采用高性能 Fluoroelastomer 材料，坚韧耐用却又异常柔软，并搭配创新的按扣加收拢式表扣。'),
      ),
      WatchPageModel(
        image: 'assets/images/icon_watch_4.png',
        color: Color(0xff4E5160),
        description: WatchPageModel.descriptionWidget(
            model: '皮制回环形表带\n\n',
            price: 3199,
            intro:
                '不锈钢表壳经久耐用，表层经过抛光处理，呈现镜面般闪亮的光泽。\n\n皮制回环形表带采用威尼斯皮革手工打造而成，内藏磁体，只需将表带绕于腕间，就能与手腕完美贴合，简洁利落。'),
      ),
    ];
  }

  /// 底部描述视图
  static Widget descriptionWidget({
    required String model,
    required int price,
    required String intro,
  }) {
    return Text.rich(
      TextSpan(
        style: TextStyle(
          color: Colors.white,
          fontSize: 18,
          fontWeight: FontWeight.bold,
        ),
        children: [
          TextSpan(text: model),
          TextSpan(
            text: 'RMB $price 起\n\n',
            style: TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 17,
            ),
          ),
          TextSpan(
            text: intro,
            style: TextStyle(
              fontSize: 13,
              fontWeight: FontWeight.normal,
            ),
          ),
        ],
      ),
    );
  }
}

/// 核心绘制类（主要是根据动画进度来渲染背景和动画）
class FlowPainter extends CustomPainter {
  final BuildContext context;

  /// 动画进度
  final ValueNotifier<double> animationProgress;

  /// 底部按钮的 key
  final GlobalKey target;

  /// 变化的颜色列表
  final List<Color> colors;

  /// 当前的 render box
  RenderBox? _renderBox;

  FlowPainter({
    required this.context,
    required this.animationProgress,
    required this.target,
    required this.colors,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final screeSize = MediaQuery.of(context).size;

    _renderBox ??= target.currentContext!.findRenderObject() as RenderBox?;

    /// 开始拖动的页面
    final page = animationProgress.value.floor();

    /// 动画进度（百分比）
    final progress = animationProgress.value - page;

    final targetPosition = _renderBox!.localToGlobal(Offset.zero);

    final xScale = screeSize.height * 8;
    final yScale = xScale / 2;

    /// 根据进度计算当前的动画曲线， 主要用于动画在不同时机的速率
    var curvedValue = Curves.easeInOut.transformInternal(progress);

    /// 逆转动画曲线，作用同上
    final reverseValue = 1 - curvedValue;

    Paint buttonPaint = Paint();
    Paint backgroundPaint = Paint();

    Rect buttonRect = Rect.fromLTWH(0, 0, screeSize.width, screeSize.height);
    Rect backgroundRect =
        Rect.fromLTWH(0, 0, screeSize.width, screeSize.height);

    if (progress < 0.5) {
      backgroundPaint.color = colors[page % colors.length];
      buttonPaint.color = colors[(page + 1) % colors.length];
      buttonRect = Rect.fromLTRB(
        targetPosition.dx - (xScale * curvedValue),
        targetPosition.dy - (yScale * curvedValue),
        targetPosition.dx + _renderBox!.size.width * reverseValue,
        targetPosition.dy + _renderBox!.size.height + (yScale * curvedValue),
      );
    } else {
      backgroundPaint.color = colors[(page + 1) % colors.length];
      buttonPaint.color = colors[page % colors.length];
      buttonRect = Rect.fromLTRB(
        targetPosition.dx + _renderBox!.size.width * reverseValue,
        targetPosition.dy - (yScale * reverseValue),
        targetPosition.dx + _renderBox!.size.width + xScale * reverseValue,
        targetPosition.dy + _renderBox!.size.height + (yScale * reverseValue),
      );
    }

    /// 绘制背景
    canvas.drawRect(backgroundRect, backgroundPaint);

    canvas.drawRRect(
      RRect.fromRectAndRadius(buttonRect, Radius.circular(screeSize.height)),
      buttonPaint,
    );
  }

  /// 这里设置总是重新绘制（因为动画进度在不断变化）
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
